home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #5
/
Amiga Plus CD - 2000 - No. 5.iso
/
Tools
/
Dev
/
FPSE_src
/
emu.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
12KB
|
471 lines
/*
FPSE main()
===========
Written by BERO
Modified by LDChen
*/
#include "fpse.h"
// FPSE can use this executables:
#define PSX_EXE 1
#define CPE_EXE 2
#define COFF_EXE 3
#define INVALID_EXE 4
// Actually these are unused, but in the future...
#if 0
// Section names of COFF format:
static char text_name[] = { ".text" };
static char rdata_name[] = { ".rdata" };
static char data_name[] = { ".data" };
static char sdata_name[] = { ".sdata" };
static char sbss_name[] = { ".sbss" };
static char bss_name[] = { ".bss" };
static char *COFF_Names[8] = {
text_name,
rdata_name,
data_name,
sdata_name,
sbss_name,
bss_name,
NULL,
NULL
};
#endif
#define SCOFF_TEXT 0
#define SCOFF_RDATA 1
#define SCOFF_DATA 2
#define SCOFF_SDATA 3
#define SCOFF_SBSS 4
#define SCOFF_BSS 5
#define SCOFF_UNKNOWN 6
unsigned char *rom,*ram,*scratchpad,*extrom;
int FPSE_Flags = EMULATE_BIOS | COMPILE;
extern int breakpoint;
static char ActionR[] = { "ar.rom" };
static UINT32 FSize(FILE *f)
{
UINT32 curpos = ftell(f);
UINT32 endpos;
fseek(f,0L,SEEK_END);
endpos = ftell(f);
fseek(f,curpos,SEEK_SET);
return endpos;
}
static int PSXGetFileType(FILE *f)
{
UINT32 current;
UINT8 mybuf[2048];
EXE_HEADER *exe_hdr;
FILHDR *coff_hdr;
current = ftell(f);
fseek(f,0L,SEEK_SET);
fread(mybuf,2048,1,f);
fseek(f,current,SEEK_SET);
exe_hdr = (EXE_HEADER *)mybuf;
if (memcmp(exe_hdr->id,"PS-X EXE",8)==0)
return PSX_EXE;
if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E')
return CPE_EXE;
coff_hdr = (FILHDR *)mybuf;
if (coff_hdr->f_magic == 0x0162)
return COFF_EXE;
return INVALID_EXE;
}
#if 0
static int COFFSectionName(char *str)
{
int x;
COFF_Names[SCOFF_UNKNOWN] = str;
for (x=SCOFF_TEXT; x<=SCOFF_UNKNOWN; x++)
if (!strcmp(str,COFF_Names[x])) break;
return x;
}
#endif
static int PSXLoadFile(char *nf, UINT32 addr, int flags)
{
FILE *fp;
EXE_HEADER head;
int type;
int size;
UINT8 *mybuf;
UINT8 *buf;
FILHDR *coff_hdr;
AOUTHDR *opt_hdr;
SCNHDR *section;
fp = fopen(nf,"rb");
if (fp==NULL) return FPSE_ERR;
if (addr)
{
printf("Loading %s at %08x\n",nf,(int)addr);
size = FSize(fp);
fread(ram + (addr & 0x1FFFFF),1,size,fp);
} else {
type = PSXGetFileType(fp);
switch (type) {
case PSX_EXE:
fread(&head,1,sizeof(head),fp);
head.t_addr = SWAP32(head.t_addr);
head.t_size = SWAP32(head.t_size);
head.pc0 = SWAP32(head.pc0);
head.s_addr = SWAP32(head.s_addr);
printf("Loading %s (PS_EXE) at %08x-%08x\n",
nf,(int)head.t_addr,(int)head.t_addr+(int)head.t_size);
fread(&ram[head.t_addr&0x1fffff],1,head.t_size,fp);
if (flags)
{
printf("Setting up PC=%08x\n",(int)head.pc0);
setpc(head.pc0);
reg.r[30] = reg.r[29] = head.s_addr;
reg.r[31] = 0;
}
break;
case CPE_EXE:
printf("Loading %s (CPE_EXE)\n",nf);
size = FSize(fp);
mybuf = (UINT8*)malloc(size);
fread(mybuf,1,size,fp);
buf = mybuf + 6;
while (*buf)
{
switch (*buf) {
case 3:
if (flags)
{
UINT32 myPc = *(UINT32 *)(buf + 3);
printf("Setting up PC=%08x\n",(int)myPc);
setpc(myPc);
reg.r[30] = reg.r[29] = 0x801FFFF0;
reg.r[31] = 0;
buf += 7;
}
break;
case 1:
{
UINT32 base,size;
base = *(UINT32 *)(buf + 1);
size = *(UINT32 *)(buf + 5);
PRINTF("Base Address = 0x%08x Size = 0x%08x(%d)\n" ,
(int)base , (int)size , (int)size);
memcpy(&ram[base & 0x1FFFFF], buf + 9, size);
buf += 9+size;
break;
}
default:
printf("Unknown id field 0x%02x at offset 0x%08x" ,
*buf, (int)(buf - mybuf));
free(mybuf);
fclose(fp);
return FPSE_ERR;
}
}
free(mybuf);
break;
case COFF_EXE:
printf("Loading %s (COFF_EXE)\n",nf);
size = FSize(fp);
mybuf = (UINT8*)malloc(size);
fread(mybuf,1,size,fp);
coff_hdr = (FILHDR *)mybuf;
opt_hdr = (AOUTHDR*)(coff_hdr+1);
section = (SCNHDR *)(mybuf + FILHSZ + coff_hdr->f_opthdr);
if (flags)
{
printf("Setting up PC=%08x\n",(int)opt_hdr->entry);
setpc(0x80010030);
reg.r[30] = reg.r[29] = 0x801fff00;
reg.r[31] = opt_hdr->entry;
}
for (size = 0; size < coff_hdr->f_nscns ; size++)
{
/*
if (flags)
{
switch (COFFSectionName(section->s_name)) {
case SCOFF_BSS:
break;
}
}
*/
PRINTF("%8s at %08x size %08x\n",
section->s_name,
(int)section->s_paddr,
(int)section->s_size);
if (section->s_scnptr)
memcpy(&ram[(section->s_paddr) & 0x1FFFFF],
mybuf+section->s_scnptr,section->s_size);
else memset(&ram[(section->s_paddr) & 0x1FFFFF],
0,section->s_size);
section++;
}
free(mybuf);
break;
case INVALID_EXE:
printf("ERROR: %s not a valid EXE file.\n",nf);
break;
}
}
fclose(fp);
return FPSE_OK;
}
static char helpmsg[] =
"\nSyntax: fpse [-option] [file]\n"
" file PSX-EXE file\n"
" -c compiler(default)\n"
" -i interpriter\n"
" -b<biosfile> bios filename\n"
" -a<romfile> load A/R Flash\n"
" -v verbose\n"
" -d disassemble\n"
" -e run debugger\n"
" -s<script> script file name\n"
" -? display this help screen\n";
int main(int argc,char *argv[])
{
FILE *fp = NULL;
char *file = NULL;
char *scriptfile = NULL;
char *flashfile = NULL;
char buffer[80];
char cmd[8];
char filename[80];
UINT32 address;
int i,line;
// breakpoint = 0x8003ace8;
printf("FPSE - *FREE* PlayStation Emulator\n"
"%s Version %2x.%02x\n\n"
"Written by BERO and LDCHEN\n",
OS_Name,FPSE_VERSION>>8, FPSE_VERSION & 0xFF);
if (OS_PorterName!=NULL)
printf("Porting done by %s\n",OS_PorterName);
LoadCFG();
for(i=1;i<argc;i++) {
char *s = argv[i];
if (s[0]=='-') {
switch(s[1]) {
case 'a':
if (*(s+2) == 0) flashfile = ActionR;
else {
flashfile = s+2;
FPSE_Flags |= ACTIONREPLAY;
}
break;
case 'c': FPSE_Flags |= COMPILE; break;
case 'i': FPSE_Flags &= ~COMPILE; break;
case 'v': FPSE_Flags |= VERBOSE; break;
case 'd': FPSE_Flags |= DISASMFLG; break;
case 'b': FPSEIni.BiosName = s+2; break;
case 'e': FPSE_Flags |= DEBUG; break;
case 's': scriptfile = s+2; break;
case '?':
default:
if (OS_CheckOption(s + 1) == FPSE_OK) break;
/* if command line error, displays Messages and exit */
INI_Free();
printf(helpmsg);
if (OS_ExtendedMsg != NULL) {
printf("\n%s specific options:\n",OS_Name);
printf("%s",OS_ExtendedMsg);
}
printf("\nPlease read 'readme.txt' and 'terms.txt'"
" before start.\n");
return -1;
}
} else file = s;
}
memalloc();
bios_init();
if (hw_init() != FPSE_OK)
{
printf("Couldn't initialize the hardware!\n");
memfree();
hw_close();
INI_Free();
return -1;
}
compile_init();
Reset();
if (FPSEIni.BiosName) {
fp = fopen(FPSEIni.BiosName,"rb");
if (fp==NULL) {
strcpy(buffer,"bios\\");
strcat(buffer,FPSEIni.BiosName);
fp = fopen(buffer,"rb");
}
if (fp==NULL) {
printf("can't load biosfile\n");
} else {
FPSE_Flags &= ~EMULATE_BIOS;
fread(rom,1,0x80000,fp);
fclose(fp);
// Now run the BIOS
i = FPSE_Flags;
FPSE_Flags &= ~(VERBOSE | DISASMFLG);
// FPSE_Flags |= VERBOSE | DISASMFLG;
while(PC != 0x80030000) doInst();
FPSE_Flags = i;
}
}
if (flashfile)
{
fp = fopen(flashfile,"rb");
if (fp==NULL) {
strcpy(buffer,"actionR\\");
strcat(buffer,flashfile);
fp = fopen(buffer,"rb");
}
if (fp==NULL) {
printf("can't load A/R %s, using defaults\n",flashfile);
flashfile = NULL;
} else {
printf("loading %s...\n",flashfile);
fread(extrom,1,0x20000,fp);
fclose(fp);
Reset();
if (emulate_bios)
{
setpc(*(UINT32 *)(extrom));
reg.r[30] = reg.r[29] = 0x801fff00;
reg.r[31] = 0;
}
}
}
PSXLoadFile("LibPS.exe",0,0);
if (scriptfile)
{
fp = fopen(scriptfile,"rt");
if (fp != NULL)
{
line = 0;
while (fgets(buffer,sizeof(buffer),fp))
{
line++;
i = sscanf(buffer,"%s %s %x",cmd,filename,(int *)&address);
if (i != 2 && i != 3)
{
printf("Syntax error in '%s' line %d.\n",scriptfile,line);
break;
} else {
if (!stricmp(cmd,"run")) {
PSXLoadFile(filename,0,1);
} else {
if (!stricmp(cmd,"load")) {
if (i==2) PSXLoadFile(filename,0,0);
else PSXLoadFile(filename,address,0);
}
}
}
}
fclose(fp);
} else printf("Script '%s' not found.\n",scriptfile);
}
if (file) PSXLoadFile(file,0,1);
if (debug) run_debug();
else
if (compile) compile_go();
else go();
INI_Free();
memfree();
hw_close();
return 0;
}
#if 1
int printlog(char *fmt, ...)
{
int ret;
va_list argp;
va_start(argp,fmt);
ret = vprintf(fmt,argp);
va_end(argp);
return ret;
}
#else
int printlog(char *fmt, ...)
{
int ret;
va_list argp;
static char buf[256],prevbuf[256];
static char *bufp=buf;
static int count;
va_start(argp,fmt);
ret = vsprintf(bufp,fmt,argp);
va_end(argp);
bufp += strlen(bufp);
if (bufp[-1] != '\n') {
return ret;
}
if (strcmp(buf,prevbuf)==0) {
count++;
} else {
if (count) { printf(" %d times\n",count+1); count=0; }
printf("%s",buf);
strcpy(prevbuf,buf);
}
bufp=buf;
return ret;
}
#endif